package tianrun.ziguan.api.calculate.config.service.template.module.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Sets;
import org.apache.shiro.util.Assert;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tianrun.ziguan.api.calculate.config.dao.TTemplateMapper;
import tianrun.ziguan.api.calculate.config.dto.request.Module;
import tianrun.ziguan.api.calculate.config.dto.request.ModulesDetailBody;
import tianrun.ziguan.api.calculate.config.dto.request.ModulesSaveBody;
import tianrun.ziguan.api.calculate.config.dto.request.common.DeleteBody;
import tianrun.ziguan.api.calculate.config.dto.request.common.add.edit.AddOrEditBody;
import tianrun.ziguan.api.calculate.config.dto.response.ModuleByTableName;
import tianrun.ziguan.api.calculate.config.entity.TCalAsset;
import tianrun.ziguan.api.calculate.config.entity.TGeModule;
import tianrun.ziguan.api.calculate.config.enums.SourceTypeEnum;
import tianrun.ziguan.api.calculate.config.service.cal.asset.ITCalAssetService;
import tianrun.ziguan.api.calculate.config.service.common.CommonService;
import tianrun.ziguan.api.calculate.config.service.ge.TGeModuleService;
import tianrun.ziguan.api.calculate.config.service.template.module.ModulesService;
import tianrun.ziguan.api.common.util.BeanUtil;
import tianrun.ziguan.api.common.util.StringUtil;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ModulesServiceImpl implements ModulesService {
    @Resource
    private TTemplateMapper templateMapper;
    private final CommonService commonService;
    private final ITCalAssetService calAssetService;

    private final TGeModuleService geModuleService;

    public ModulesServiceImpl(CommonService commonService, ITCalAssetService calAssetService, TGeModuleService geModuleService) {
        this.commonService = commonService;
        this.calAssetService = calAssetService;
        this.geModuleService = geModuleService;
    }

    @Transactional
    @Override
    public ModulesSaveBody save(ModulesSaveBody body) {
        Long sourceId = body.getSourceId();
        SourceTypeEnum sourceType = body.getSourceType();
        List<TGeModule> geModules = geModuleService.listByCType(body.getSourceType());

        HashMap<String, Set<Long>> delMap = new HashMap<>();
        body.getDelModules().forEach(module -> {
            String tableName = geModules.stream()
                    .filter(m -> Objects.equals(m.getMold(), module.getMold()) && Objects.equals(sourceType, m.getcType()))
                    .map(TGeModule::getTableName)
                    .findFirst()
                    .orElse(null);
            Assert.isTrue(StringUtil.isNotEmpty(tableName), module.getName() + "是未知类型的组件,无法删除");
            delMap.computeIfAbsent(tableName, s -> Sets.newHashSet()).add(module.getId());
        });
        delMap.forEach((tableName, ids) -> commonService.delete(DeleteBody.of(ids, tableName)));
        String assetNum = null;
        if (SourceTypeEnum.ASSET.equals(sourceType)) {
            TCalAsset asset = calAssetService.getById(sourceId);
            assetNum = asset.getAssetNum();
        }
        String finalAssetNum = assetNum;
        body.getModules().forEach(module -> {
            JSONObject jsonObject = new JSONObject(BeanUtil.beanToMap(module));
            jsonObject.put(sourceType.getFiledName(), sourceId);
            if (SourceTypeEnum.ASSET.equals(sourceType)) jsonObject.put("asset_num", finalAssetNum);
            String tableName = geModules.stream()
                    .filter(m -> Objects.equals(m.getMold(), module.getMold()) && Objects.equals(sourceType, m.getcType()))
                    .map(TGeModule::getTableName)
                    .findFirst()
                    .orElse(null);
            Assert.isTrue(StringUtil.isNotEmpty(tableName), module.getName() + "是未知类型的组件,无法保存");
            AddOrEditBody addOrEditBody = new AddOrEditBody();
            addOrEditBody.setTableName(tableName);
            addOrEditBody.setData(jsonObject);
            commonService.addOrEdit(addOrEditBody);
        });

        return detail(body);
    }

    @Override
    public ModulesSaveBody detail(ModulesDetailBody body) {
        SourceTypeEnum sourceType = body.getSourceType();
        List<TGeModule> geModules = geModuleService.listByCType(sourceType);
        Set<String> tableNames = geModules.stream().map(TGeModule::getTableName).collect(Collectors.toSet());
        List<ModuleByTableName> modules = templateMapper.queryModules(tableNames, sourceType.getFiledName(), body.getSourceId());
        modules.forEach(module -> {
            String mold = geModules.stream()
                    .filter(m -> Objects.equals(m.getTableName(), module.getTableName()) && Objects.equals(sourceType, m.getcType()))
                    .map(TGeModule::getMold)
                    .findFirst()
                    .orElse(null);
            module.setMold(mold);
        });
        ModulesSaveBody saveBody = new ModulesSaveBody();
        saveBody.setSourceId(body.getSourceId());
        saveBody.setModules(BeanUtil.copyPropertiesList(modules, Module.class));
        saveBody.setSourceType(sourceType);
        return saveBody;
    }
}